home *** CD-ROM | disk | FTP | other *** search
- // cmostr.cpp
- // modification of Microsoft Foundation Class code supporting CString, to make use
- // of CMemoryObject base class.
-
- // This is a part of the Microsoft Foundation Classes C++ library.
- // Copyright (C) 1992 Microsoft Corporation
- // All rights reserved.
- //
- // This source code is only intended as a supplement to the
- // Microsoft Foundation Classes Reference and Microsoft
- // QuickHelp and/or WinHelp documentation provided with the library.
- // See these sources for detailed information regarding the
- // Microsoft Foundation Classes product.
-
- #include "stdafx.h"
- #include <limits.h>
- #include "cmostr.h"
- #include "mobject.h"
-
- #ifdef _DEBUG
- #undef THIS_FILE
- static char BASED_CODE THIS_FILE[] = __FILE__;
- #endif
-
- #define new DEBUG_NEW
-
- /////////////////////////////////////////////////////////////////////////////
- // static class data, special inlines
-
- char FAR CMOStringChNil = '\0';
-
- // For an empty string, m_???Data will point here
- // (note: avoids a lot of NULL pointer tests when we call standard
- // C runtime libraries
-
- extern const CMOString afxEmptyString;
- // for creating empty key strings
- const CMOString afxEmptyString;
-
- void CMOString::Init()
- {
- m_nDataLength = m_nAllocLength = 0;
- m_pchData = (char FAR *)&CMOStringChNil;
- }
-
- static void NEAR PASCAL SafeDelete(char FAR * pch)
- {
- if (pch != NULL && pch != (char FAR *)&CMOStringChNil)
- // delete [] pch;
- MemoryObject::ReturnBlock (pch);
- }
-
- //////////////////////////////////////////////////////////////////////////////
- // Construction/Destruction
-
- CMOString::CMOString()
- {
- Init();
- }
-
- CMOString::CMOString(const CMOString& stringSrc)
- {
- // if constructing a CMOString from another CMOString, we make a copy of the
- // original string data to enforce value semantics (i.e. each string
- // gets a copy of it's own
-
- stringSrc.AllocCopy(*this, stringSrc.m_nDataLength, 0, 0);
- }
-
- void CMOString::AllocBuffer(int nLen)
- // always allocate one extra character for '\0' termination
- // assumes [optimistically] that data length will equal allocation length
- {
- ASSERT(nLen >= 0);
- ASSERT(nLen <= INT_MAX - 1); // max size (enough room for 1 extra)
-
- if (nLen == 0)
- {
- Init();
- }
- else
- {
- // typedef char FAR fc;
- // m_pchData = new fc;
- // char FAR * tmp, * tmp_a;
- // tmp = new fc;
- // tmp_a = new fc [nLen+1];
- // m_pchData = new fc [nLen+1]; // may throw an exception
- m_pchData = (char FAR *) MemoryObject::AllocateBlock (nLen + 1); // may throw an exception
- m_pchData[nLen] = '\0';
- m_nDataLength = nLen;
- m_nAllocLength = nLen;
- }
- }
-
- void CMOString::Empty()
- {
- SafeDelete(m_pchData);
- Init();
- ASSERT(m_nDataLength == 0);
- ASSERT(m_nAllocLength == 0);
- }
-
- CMOString::~CMOString()
- // free any attached data
- {
- SafeDelete(m_pchData);
- }
-
- //////////////////////////////////////////////////////////////////////////////
- // Helpers for the rest of the implementation
-
- static inline int SafeStrlen(const char FAR * psz)
- { return (psz == NULL) ? NULL : _fstrlen(psz); }
-
- void CMOString::AllocCopy(CMOString& dest, int nCopyLen, int nCopyIndex,
- int nExtraLen) const
- {
- // will clone the data attached to this string
- // allocating 'nExtraLen' characters
- // Places results in uninitialized string 'dest'
- // Will copy the part or all of original data to start of new string
-
- int nNewLen = nCopyLen + nExtraLen;
-
- if (nNewLen == 0)
- {
- dest.Init();
- }
- else
- {
- dest.AllocBuffer(nNewLen);
- _fmemcpy(dest.m_pchData, &m_pchData[nCopyIndex], nCopyLen);
- }
- }
-
- //////////////////////////////////////////////////////////////////////////////
- // More sophisticated construction
-
- CMOString::CMOString(const char FAR * psz)
- {
- int nLen;
- if ((nLen = SafeStrlen(psz)) == 0)
- Init();
- else
- {
- AllocBuffer(nLen);
- _fmemcpy(m_pchData, psz, nLen);
- }
- }
-
- //////////////////////////////////////////////////////////////////////////////
- // Diagnostic support
-
- #ifdef _DEBUG
-
- CDumpContext&
- AFXAPI operator <<(CDumpContext& dc, const CMOString& string)
- {
- dc << string.m_pchData;
- return dc;
- }
-
- #endif //_DEBUG
-
- //////////////////////////////////////////////////////////////////////////////
- // Assignment operators
- // All assign a new value to the string
- // (a) first see if the buffer is big enough
- // (b) if enough room, copy on top of old buffer, set size and type
- // (c) otherwise free old string data, and create a new one
- //
- // All routines return the new string (but as a 'const CMOString&' so that
- // assigning it again will cause a copy, eg: s1 = s2 = "hi there".
- //
-
- void CMOString::AssignCopy(int nSrcLen, const char FAR * pszSrcData)
- {
- // check if it will fit
- if (nSrcLen > m_nAllocLength)
- {
- // it won't fit, allocate another one
- Empty();
- AllocBuffer(nSrcLen);
- }
- if (nSrcLen != 0)
- _fmemcpy(m_pchData, pszSrcData, nSrcLen);
- m_nDataLength = nSrcLen;
- m_pchData[nSrcLen] = '\0';
- }
-
- const CMOString&
- CMOString::operator =(const CMOString& stringSrc)
- {
- AssignCopy(stringSrc.m_nDataLength, stringSrc.m_pchData);
- return *this;
- }
-
- const CMOString&
- CMOString::operator =(const char FAR * psz)
- {
- AssignCopy(SafeStrlen(psz), psz);
- return *this;
- }
-
-
- //////////////////////////////////////////////////////////////////////////////
- // concatenation
-
- // NOTE: "operator +" is done as friend functions for simplicity
- // There are three variants:
- // CMOString + CMOString
- // and for ? = char, const char FAR *
- // CMOString + ?
- // ? + CMOString
-
- void
- CMOString::ConcatCopy(int nSrc1Len, const char FAR * pszSrc1Data,
- int nSrc2Len, const char FAR * pszSrc2Data)
- {
- // -- master concatenation routine
- // Concatenate two sources
- // -- assume that 'this' is a new CMOString object
-
- int nNewLen = nSrc1Len + nSrc2Len;
- AllocBuffer(nNewLen);
- _fmemcpy(m_pchData, pszSrc1Data, nSrc1Len);
- _fmemcpy(&m_pchData[nSrc1Len], pszSrc2Data, nSrc2Len);
- }
-
- CMOString
- AFXAPI operator +(const CMOString& string1, const CMOString& string2)
- {
- CMOString s;
- s.ConcatCopy(string1.m_nDataLength, string1.m_pchData,
- string2.m_nDataLength, string2.m_pchData);
- return s;
- }
-
- CMOString
- AFXAPI operator +(const CMOString& string, const char FAR * psz)
- {
- CMOString s;
- s.ConcatCopy(string.m_nDataLength, string.m_pchData, SafeStrlen(psz), psz);
- return s;
- }
-
-
- CMOString
- AFXAPI operator +(const char FAR * psz, const CMOString& string)
- {
- CMOString s;
- s.ConcatCopy(SafeStrlen(psz), psz, string.m_nDataLength, string.m_pchData);
- return s;
- }
-
- //////////////////////////////////////////////////////////////////////////////
- // concatenate in place
-
- void
- CMOString::ConcatInPlace(int nSrcLen, const char FAR * pszSrcData)
- {
- // -- the main routine for += operators
-
- // if the buffer is too small, or we have a width mis-match, just
- // allocate a new buffer (slow but sure)
- if (m_nDataLength + nSrcLen > m_nAllocLength)
- {
- // we have to grow the buffer, use the Concat in place routine
- char FAR * pszOldData = m_pchData;
- ConcatCopy(m_nDataLength, pszOldData, nSrcLen, pszSrcData);
- ASSERT(pszOldData != NULL);
- SafeDelete(pszOldData);
- }
- else
- {
- // fast concatenation when buffer big enough
- _fmemcpy(&m_pchData[m_nDataLength], pszSrcData, nSrcLen);
- m_nDataLength += nSrcLen;
- }
- ASSERT(m_nDataLength <= m_nAllocLength);
- m_pchData[m_nDataLength] = '\0';
- }
-
- const CMOString&
- CMOString::operator +=(const char FAR * psz)
- {
- ConcatInPlace(SafeStrlen(psz), psz);
- return *this;
- }
-
- const CMOString&
- CMOString::operator +=(char ch)
- {
- ConcatInPlace(1, &ch);
- return *this;
- }
-
- const CMOString&
- CMOString::operator +=(const CMOString& string)
- {
- ConcatInPlace(string.m_nDataLength, string.m_pchData);
- return *this;
- }
-
-
- ///////////////////////////////////////////////////////////////////////////////
- // Advanced direct buffer access
-
- char FAR * CMOString::GetBuffer(int nMinBufLength)
- {
- ASSERT(nMinBufLength >= 0);
-
- if (nMinBufLength > m_nAllocLength)
- {
- // we have to grow the buffer
- char FAR * pszOldData = m_pchData;
- int nOldLen = m_nDataLength; // AllocBuffer will tromp it
-
- AllocBuffer(nMinBufLength);
- _fmemcpy(m_pchData, pszOldData, nOldLen);
- m_nDataLength = nOldLen;
- m_pchData[m_nDataLength] = '\0';
-
- SafeDelete(pszOldData);
- }
-
- // return a pointer to the character storage for this string
- ASSERT(m_pchData != NULL);
- return m_pchData;
- }
-
- void CMOString::ReleaseBuffer(int nNewLength)
- {
- if (nNewLength == -1)
- nNewLength = _fstrlen(m_pchData); // zero terminated
-
- ASSERT(nNewLength <= m_nAllocLength);
- m_nDataLength = nNewLength;
- m_pchData[m_nDataLength] = '\0';
- }
-
- char FAR * CMOString::GetBufferSetLength(int nNewLength)
- {
- ASSERT(nNewLength >= 0);
-
- GetBuffer(nNewLength);
- m_nDataLength = nNewLength;
- m_pchData[m_nDataLength] = '\0';
- return m_pchData;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // Commonly used routines (rarely used routines in STREX.CPP)
-
- int CMOString::Find(char ch) const
- {
- // find a single character (strchr)
- char FAR * psz = _fstrchr(m_pchData, ch);
- return (psz == NULL) ? -1 : (int)(psz - m_pchData);
- }
-
- int CMOString::FindOneOf(const char FAR * pszCharSet) const
- {
- ASSERT(pszCharSet != NULL);
- char FAR * psz = (char FAR *) _fstrpbrk(m_pchData, pszCharSet);
- return (psz == NULL) ? -1 : (int)(psz - m_pchData);
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // Additional constructors for far string data
-
- #if defined(_NEARDATA) && defined (qq_zz_aa_dd_)
- CMOString::CMOString(LPCSTR lpsz)
- {
- int nLen;
- if (lpsz == NULL || (nLen = lstrlen(lpsz)) == 0)
- {
- Init();
- }
- else
- {
- AllocBuffer(nLen);
- _fmemcpy(m_pchData, lpsz, nLen);
- }
- }
- #endif //_NEARDATA
-
- ///////////////////////////////////////////////////////////////////////////////
-